package com.gateway.video.rtsp.handler;

import com.gateway.video.rtsp.codec.client.RtspClientCodec;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class RtspServerHandler extends ChannelInboundHandlerAdapter {

    private ByteBuf initialData;

    @Autowired
    private EventLoopGroup group;

    private volatile Channel clientChannel;

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
        ctx.read();
        initialData = ctx.alloc().buffer();
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
        ReferenceCountUtil.safeRelease(initialData);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(msg instanceof HttpRequest) {
            var request = (FullHttpRequest) msg;

            Bootstrap bootstrap = new Bootstrap()
                    .remoteAddress("192.168.45.1", 8554)
                    .group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.AUTO_READ, true)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)
                    .handler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(null, RtspClientCodec.class.getName(), new RtspClientCodec());
                            channel.pipeline().addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
                            channel.pipeline().addLast(null, RtspClientHandler.class.getName(), new RtspClientHandler(ctx));
                        }
                    });

            ChannelFuture connect = bootstrap.connect();
            Channel channel = connect.channel();
            connect.addListener(future -> {
                if(future.isSuccess()) {
                    channel.writeAndFlush(request).addListener(future1 -> {
                        if(future.isSuccess()) {
                            if(log.isDebugEnabled()) {
                                log.debug("Video server send request {}", request);
                            }
                            if(request.method().equals("SETUP")) {
                                if(log.isDebugEnabled()) {
                                    log.debug("Video server session connect success");
                                }
                            }
                            this.clientChannel = channel;
                            channel.read();
                        }else {
                            if(log.isErrorEnabled()) {
                                log.error("Video server send request fail", future1.cause());
                            }
                            ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY)).addListener(ChannelFutureListener.CLOSE);
                        }
                    });
                }else {
                    if(log.isErrorEnabled()) {
                        log.error("Video server connect fail", future.cause());
                    }
                    ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY)).addListener(ChannelFutureListener.CLOSE);
                }
            });
        }
    }
}
